//
//  Object.h
//  Simulation
//
//  Created by Christopher Kemsley on 2/27/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#ifndef Simulation_Object_h
#define Simulation_Object_h

#include "Exception.hpp"


NamespaceBegin




class	Object
{
public:
	
	Object () ;
	
	
	// Reference-counted memory management
	void	retain () ;
	void	release () ;
	void	autorelease () ;
	
	
protected:
	virtual ~Object() ;
	
private:
	unsigned	mRetainCount ;
} ;






template <typename Type>
struct	OP
{
	
	OP	()							: mValue(0) { }
	OP	( Type * inP )				: mValue(inP) {if(inP!=0){inP->retain();}}
	OP	( OP<Type> const & inP )	: mValue(inP.mValue) {if(mValue!=0){mValue->retain();}}
	~OP	()							{ if(mValue!=0)mValue->release(); }
	
	
	Type*	operator->	() const
		{
		return mValue ;
		}
	Type&	operator*	() const
		{
		return *mValue ;
		}
	
	
	Type*	pointer		() const
		{
		return mValue ;
		}
	
	/* Setting */
	OP<Type>&	operator=	( Type * inP )
		{
		if ( mValue != 0 )
			mValue -> release () ;
		mValue = inP ;
		if ( mValue != 0 )
			mValue -> retain () ;
		return *this ;
		}
	OP<Type>&	operator=	( OP<Type> const & inP )
		{
		if ( mValue != 0 )
			mValue -> release () ;
		mValue = inP.mValue ;
		if ( mValue != 0 )
			mValue -> retain () ;
		return *this ;
		}
	OP<Type>&	operator<<	( Type * inP )
		{
		if ( mValue != 0 )
			mValue -> release () ;
		mValue = inP ;
		return *this ;
		}
	OP<Type>&	operator<<	( OP<Type> & inP )	// steals the object
		{
		if ( mValue != 0 )
			mValue -> release () ;
		mValue = inP.mValue ;
		inP.mValue = 0 ;
		return *this ;
		}
	
	/* Comparing */
	bool		operator==	( Type * inP ) const
		{
		return mValue == inP ;
		}
	bool		operator==	( OP<Type> const & inP ) const
		{
		return mValue == inP.mValue ;
		}
	bool		operator!=	( Type * inP ) const
		{
		return mValue != inP ;
		}
	bool		operator!=	( OP<Type> const & inP ) const
		{
		return mValue != inP.mValue ;
		}
	
	/* std::vector and set require these */
	bool		operator<	( Type * inP ) const
		{
		return mValue < inP ;
		}
	bool		operator<	( OP<Type> const & inP ) const
		{
		return mValue < inP.mValue ;
		}
	bool		operator>	( Type * inP ) const
		{
		return mValue > inP ;
		}
	bool		operator>	( OP<Type> const & inP ) const
		{
		return mValue > inP.mValue ;
		}
	
private:
	Type	*	mValue ;
} ;






template <typename Type>
struct	DP
{
	
	DP	()					: mValue(0) { }
	DP	( Type * inP )		: mValue(inP) { }
	~DP	()					{ if(mValue!=0)delete mValue; }
	
	
	Type*	operator->	() const
		{
		return mValue ;
		}
	Type&	operator*	() const
		{
		return *mValue ;
		}
	
	
	Type*	pointer		() const
		{
		return mValue ;
		}
	
	/* Setting */
	DP<Type>&	operator<<	( Type * inP )
		{
		if ( mValue != 0 )
			delete mValue ;
		mValue = inP ;
		return *this ;
		}
	DP<Type>&	operator<<	( DP<Type> & inP )	// steals the object
		{
		if ( mValue != 0 )
			delete mValue ;
		mValue = inP.mValue ;
		inP.mValue = 0 ;
		return *this ;
		}
	
	/* Comparing */
	bool		operator==	( Type * inP ) const
		{
		return mValue == inP ;
		}
	bool		operator==	( DP<Type> const & inP ) const
		{
		return mValue == inP.mValue ;
		}
	bool		operator!=	( Type * inP ) const
		{
		return mValue != inP ;
		}
	bool		operator!=	( DP<Type> const & inP ) const
		{
		return mValue != inP.mValue ;
		}
	
	/* std::vector and set require these */
	bool		operator<	( Type * inP ) const
		{
		return mValue < inP ;
		}
	bool		operator<	( DP<Type> const & inP ) const
		{
		return mValue < inP.mValue ;
		}
	bool		operator>	( Type * inP ) const
		{
		return mValue > inP ;
		}
	bool		operator>	( DP<Type> const & inP ) const
		{
		return mValue > inP.mValue ;
		}
	
private:
	Type	*	mValue ;
	
	// Declared but not implemented
	DP<Type>&	operator=	( Type * inP ) ;
	DP<Type>&	operator=	( DP<Type> const & inP ) ;
} ;




NamespaceEnd

#endif
